﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using PSE.Updater.Common.Gateway.ServiceContract;
using PSE.Updater.Common.Gateway.DataContract;
using PSE.Updater.Server.Engine;
using System.IO;
using PSE.Updater.Common;
using PSE.Updater.Server.Engine.Providers.Updates;
using Engine = PSE.Updater.Server.Engine;
using PSE.Updater.Common.Providers;
using PSE.Framework.ErrorLogging;
using PSE.Updater.Common.Providers.Interfaces;

namespace PSE.Updater.Server.Service
{
    [ServiceBehavior(IncludeExceptionDetailInFaults = true)]
    public class UpdatesDownloadService : IUpdatesDownloadService
    {
        public Stream DownloadUpdatePackage(ProviderType type, ModuleUpdatePackage moduleUpdatePackage)
        {
            if (moduleUpdatePackage == null)
            {
                Exception ex = new Exception("O pacote para download deve ser informado");
                ThrowFaultException(ex);
                return Stream.Null;
            }
            string filePath = string.Empty;

            try
            {
                var update = Engine.UpdateService.Instance.GetAvaliableFile(type, new ModuleVersion
                                                                           {
                                                                               Version = moduleUpdatePackage.Version,
                                                                               SystemName = moduleUpdatePackage.SystemName,
                                                                               ModuleName = moduleUpdatePackage.ModuleName
                                                                           });


                if (update != null)
                {
                    filePath = update.FilePath;
                    if (File.Exists(filePath))
                    {
                        Stream file = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
                        return file;
                    }
                    else
                    {
                        System.IO.FileNotFoundException ex = new System.IO.FileNotFoundException(filePath);
                        ThrowFaultException(ex);
                    }
                }
            }
            catch (Exception ex)
            {
                ThrowFaultException(ex);
            }
            return Stream.Null;
        }

        private string SaveFile(Stream packageFile, string name, string downloadPath)
        {
            string filePath = string.Empty;

            if (packageFile != Stream.Null)
            {
                byte[] buffer;
                int count, readed;

                //se o arquivo ja existir, apagar
                FileInfo file = new FileInfo(name);
                filePath = Path.Combine(downloadPath, file.Name);
                if (File.Exists(filePath))
                    File.Delete(filePath);

                //ler o stream e salvar o arquivo em disco
                using (FileStream fs = new FileStream(filePath, FileMode.CreateNew))
                {
                    readed = 0;
                    count = 20480;
                    buffer = new byte[count];
                    while ((readed = packageFile.Read(buffer, 0, count)) > 0)
                    {
                        fs.Write(buffer, 0, readed);
                        buffer = new byte[count];
                    }
                }

                packageFile.Close();
            }
            if (!File.Exists(filePath))
            {
                ErrorLogger.WriteLog(LogType.Error, new FileNotFoundException(filePath));
                return string.Empty;
            }
            else
            {
                FileInfo fileInfo = new FileInfo(filePath);
                if (fileInfo.Length == 0)
                {
                    Exception ex = new Exception(string.Format("Arquivo {0} corrompido ou inválido", filePath));
                    ErrorLogger.WriteLog(LogType.Error, ex);

                    return string.Empty;
                }
            }
            return filePath;
        }

        public void ThrowFaultException(Exception ex)
        {
            ErrorLogger.WriteLog(LogType.Error, ex);
            throw new FaultException(new FaultReason(ex.ToString()), new FaultCode(ex.Message));
        }
    }
}
